import {hash256} from "@blitzjs/auth"
import {SecurePassword} from "@blitzjs/auth/secure-password"
import {resolver} from "@blitzjs/rpc"
import db from "db"
import {ResetPassword} from "../validations"
import login from "./login"

export class ResetPasswordError extends Error {
  name = "ResetPasswordError"
  message = "Reset password link is invalid or it has expired."
}

export default resolver.pipe(resolver.zod(ResetPassword), async ({password, token}, ctx) => {
  if (!token) throw new ResetPasswordError("Token is required")
  // 1. Try to find this token in the database
  const hashedToken = hash256(token)
  const possibleToken = await db.token.findFirst({
    where: {hashedToken, type: "RESET_PASSWORD"},
    include: {user: true},
  })

  // 2. If token not found, error
  if (!possibleToken) {
    throw new ResetPasswordError()
  }
  const savedToken = possibleToken

  // 3. Delete token so it can't be used again
  await db.token.delete({where: {id: savedToken.id}})

  // 4. If token has expired, error
  if (savedToken.expiresAt < new Date()) {
    throw new ResetPasswordError()
  }

  // 5. Since token is valid, now we can update the user's password
  const hashedPassword = await SecurePassword.hash(password.trim())
  const user = await db.user.update({
    where: {id: savedToken.userId},
    data: {hashedPassword},
  })

  // 6. Revoke all existing login sessions for this user
  await db.session.deleteMany({where: {userId: user.id}})

  // 7. Now log the user in with the new credentials
  await login({email: user.email, password}, ctx)

  return true
})
